package code.limiter;

import java.util.concurrent.CountDownLatch;

public class LeakyBucket {
    private long rate; // 桶的流出速率，每秒
    private long capacity; // 桶的大小
    private long size; // 当前桶的大小
    private long lastLeakyTime; // 上次流出时间, 精确到秒

    private final Object lock = new Object();

    public LeakyBucket(long _rate, long _capacity) {
        rate = _rate;
        capacity = _capacity;
        size = 0;
        lastLeakyTime = System.currentTimeMillis() / 1000;
    }

    public boolean allow() {
        // 加锁
        synchronized(lock) {
            // 计算距离流出 应该流出的水量
            long now = System.currentTimeMillis() / 1000;
            long leakyWater = (now - lastLeakyTime) * rate;
            size -= leakyWater;
            if (size < 0) {
                size = 0;
            }
            lastLeakyTime = now;
            if (size >= capacity){
                // 桶满了
                return false;
            }
            size++; // 流入请求
            return true;
        }
    }

    public static void main(String[] args) throws Exception {
        LeakyBucket limiter = new LeakyBucket(3, 3); // 限制每秒3个请求，桶的大小为3
        CountDownLatch count = new CountDownLatch(10);
        for (int i=1; i<=10; i++) {
            new Thread(() -> {
                if (limiter.allow()) {
                    System.out.println("OK");
                }else {
                    System.out.println("False");
                }
                count.countDown();
            }).start();
            Thread.sleep(200); // 大约1秒5个请求
        }
        count.await();
    }
}
